#include "window.h"

#include "config.h"
#include "pipe.h"
#include "renderState.h"


#include <fstream>
#include <sstream>

namespace eqPc
{

bool Window::configInitSystemWindow( const eq::uint128_t& initID )
{
#ifndef Darwin
    if( !eq::Window::configInitSystemWindow( initID ))
        return false;

    // OpenGL version is less than 2.0.
    if( !GLEW_EXT_framebuffer_object )
    {
        if( getDrawableConfig().accumBits )
            return true;

        configExitSystemWindow();
#endif
        // try with 64 bit accum buffer
        setIAttribute( IATTR_PLANES_ACCUM, 16 );
        if( eq::Window::configInitSystemWindow( initID ))
            return true;

        // no anti-aliasing possible
        setIAttribute( IATTR_PLANES_ACCUM, eq::AUTO );

        return eq::Window::configInitSystemWindow( initID );

#ifndef Darwin
    }

    return true;
#endif
}

bool Window::configInitGL( const eq::uint128_t& initID )
{
    if( !eq::Window::configInitGL( initID ))
        return false;

    glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, 1 );
    glEnable( GL_CULL_FACE ); // OPT - produces sparser images in DB mode
    glCullFace( GL_BACK );

    EQASSERT( !_state );
    _state = new RenderState( getObjectManager( ));

    const Config*   config   = static_cast< const Config* >( getConfig( ));
    const InitData& initData = config->getInitData();

    if( initData.showLogo( ))
        _loadLogo();

    if( initData.useGLSL() )
        _loadShaders();

    return true;
}

bool Window::configExitGL()
{
    if( _state && !_state->isShared( ))
        _state->deleteAll();

    delete _state;
    _state = 0;

    return eq::Window::configExitGL();
}

//namespace
//{
//#ifdef EQ_RELEASE
//#  ifdef _WIN32 // final INSTALL_DIR is not known at compile time
//static const std::string _logoTextureName =
//                              std::string( "../share/Equalizer/data/logo.rgb" );
//#  else
//static const std::string _logoTextureName = std::string( EQ_INSTALL_DIR ) +
//                                 std::string( "share/Equalizer/data/logo.rgb" );
//#  endif
//#else
//static const std::string _logoTextureName = std::string( EQ_SOURCE_DIR ) +
//                                       std::string( "examples/eqPly/logo.rgb" );
//#endif
//}

void Window::_loadLogo()
{
    //if( !GLEW_ARB_texture_rectangle )
    //{
    //    EQWARN << "Can't load overlay logo, GL_ARB_texture_rectangle not "
    //           << "available" << std::endl;
    //    return;
    //}

    //eq::Window::ObjectManager* om = getObjectManager();
    //_logoTexture = om->getEqTexture( _logoTextureName.c_str( ));
    //if( _logoTexture )
    //    return;

    //eq::Image image;
    //if( !image.readImage( _logoTextureName, eq::Frame::BUFFER_COLOR ))
    //{
    //    EQWARN << "Can't load overlay logo " << _logoTextureName << std::endl;
    //    return;
    //}

    //_logoTexture = om->newEqTexture( _logoTextureName.c_str(),
    //                                 GL_TEXTURE_RECTANGLE_ARB );
    //EQASSERT( _logoTexture );
    //
    //image.upload(eq::Frame::BUFFER_COLOR, _logoTexture, eq::Vector2i::ZERO, om);
    //EQVERB << "Created logo texture of size " << _logoTexture->getWidth() << "x"
    //       << _logoTexture->getHeight() << std::endl;
}

void Window::_loadShaders()
{
    //if( _state->getShader( vertexShader_glsl ) !=
    //    RenderState::INVALID )
    //{
    //    // already loaded
    //    return;
    //}

    //// Check if functions are available
    //if( !GLEW_VERSION_2_0 )
    //{
    //    EQWARN << "Shader function pointers missing, using fixed function "
    //           << "pipeline" << std::endl;
    //    return;
    //}

    //const GLuint vShader = _state->newShader( vertexShader_glsl,
    //                                          GL_VERTEX_SHADER );
    //EQASSERT( vShader != VertexBufferState::INVALID );
    //const GLchar* vShaderPtr = vertexShader_glsl;
    //glShaderSource( vShader, 1, &vShaderPtr, 0 );
    //glCompileShader( vShader );

    //GLint status;
    //glGetShaderiv( vShader, GL_COMPILE_STATUS, &status );
    //if( !status )
    //{
    //    EQWARN << "Failed to compile vertex shader" << std::endl;
    //    return;
    //}
    //
    //const GLuint fShader = 
    //    _state->newShader( fragmentShader_glsl, GL_FRAGMENT_SHADER );
    //EQASSERT( fShader != RenderState::INVALID );
    //const GLchar* fShaderPtr = fragmentShader_glsl;
    //glShaderSource( fShader, 1, &fShaderPtr, 0 );
    //glCompileShader( fShader );
    //glGetShaderiv( fShader, GL_COMPILE_STATUS, &status );
    //if( !status )
    //{
    //    EQWARN << "Failed to compile fragment shader" << std::endl;
    //    return;
    //}
    //
    //const GLuint program = _state->newProgram( getPipe() );
    //EQASSERT( program != RenderState::INVALID );
    //glAttachShader( program, vShader );
    //glAttachShader( program, fShader );
    //glLinkProgram( program );
    //glGetProgramiv( program, GL_LINK_STATUS, &status );
    //if( !status )
    //{
    //    EQWARN << "Failed to link shader program" << std::endl;
    //    return;
    //}
    //
    //// turn off OpenGL lighting if we are using our own shaders
    //glDisable( GL_LIGHTING );

    //EQINFO << "Shaders loaded successfully" << std::endl;
}

void Window::frameStart( const eq::uint128_t& frameID, const uint32_t frameNumber )
{
    const Pipe*      pipe      = static_cast<Pipe*>( getPipe( ));
    const FrameData& frameData = pipe->getFrameData();

    _state->setRenderMode( frameData.getRenderMode( ));
    eq::Window::frameStart( frameID, frameNumber );
}

}
